Avoiding extra byte copy inside FileSystemImpl.readFileInternal#5677
Avoiding extra byte copy inside FileSystemImpl.readFileInternal#5677doxlik wants to merge 3 commits intoeclipse-vertx:masterfrom
Conversation
40030e7 to
0ee2869
Compare
vertx-core/src/main/java/io/vertx/core/file/impl/FileSystemImpl.java
Outdated
Show resolved
Hide resolved
vertx-core/src/main/java/io/vertx/core/file/impl/FileSystemImpl.java
Outdated
Show resolved
Hide resolved
vertx-core/src/main/java/io/vertx/core/file/impl/FileSystemImpl.java
Outdated
Show resolved
Hide resolved
| Path target = resolveFile(path).toPath(); | ||
| byte[] bytes = Files.readAllBytes(target); | ||
| return Buffer.buffer(bytes); | ||
| ByteBuf bb = Unpooled.wrappedBuffer(bytes); |
There was a problem hiding this comment.
@vietj : this is ok? Or you prefer to add a new constructor to `BufferImpl' which still uses the existing Vertx heap types eg VertxUnsafeHeapByteBuf/VertxHeapByteBuf ?
The reason I'm asking is:
Unpooled::wrappedBufferstill have Netty reference count checks under the hood, implemented - which have a cost- IIRC Vertx itself contains checks to make sure the allocator of a vertx buffer is "known" to vertx e.g.
One pain point is that AFAIK Netty's heap buffers (one of the two variant) doesn't expose in public to directly set the wrapped buffer - and that's why Netty itself is using only non-Unsafe variants in Unpooled::wrappedBuffer(byte[]): if we want to do this right in Vertx we could leverage a single implementation (i.e.non-unsafe) as well or modify Netty to expose it for Unsafe variants (I can do it if needed)
|
@franz1981 thank you for your comments, I removed unrelated changes. Actually they were made by Intelij IDEA code autoformatting and I thought that maybe they are okay, but I agree that they create unnecessary noise, so next time I will try to avoid any of them. |
|
Fyi @vietj |
tsegismont
left a comment
There was a problem hiding this comment.
Thanks @doxlik and @franz1981
How about changing the perform method body to:
public Buffer perform() {
try {
Path target = resolveFile(path).toPath();
try (FileChannel fc = FileChannel.open(target, StandardOpenOption.READ)) {
BufferInternal res = BufferInternal.buffer(); // create with file size hint?
long length = fc.size();
res.getByteBuf().writeBytes(fc, 0, (int) length); // check actual size before the cast
return res;
}
} catch (IOException e) {
throw new FileSystemException(getFileAccessErrorMessage("read", path), e);
}
}It's ok to use BufferInternal in Vert.x impl classes and Netty can take care of loading and writing the file bytes appropriately.
|
It looks like that's going to allocate the @doxlik wdyt? |
|
@franz1981 Regarding the suggestion, what if file really big and bigger than 2 gb? Then here " res.getByteBuf().writeBytes(fc, 0, (int) length); // check actual size before the cast" even if we check the size, we still need to fallback to something that can handle it, either wrapping or have some "while" loop until fully read the file to the buffer. Regarding generally low level ByteBuffs stuff, it is super interesting but I have almost no solid knowledge of all its internals, so in terms of buffers / allocators optimization I fully trust to you. |
I think it's safe to stick to the behavior of If the size is bigger than |
|
@tsegismont then if we want stick to behavior of java.nio.file.Files#readAllBytes, then should we move to the channel approach as you suggested or we can simply leave the current code that already use readAllBytes? |
|
@franz1981 @vietj I also wanted to ask, what will be further process of the review / PR? I mean is it kinda in direct queue of pending PR's for Julien's review / approval or we are waiting for Vert.x 5.1.0 to proceed with this PR? |
We should move to the channel approach but, for the error cases, we can reproduce the behavior of |
Signed-off-by: doxlik <pirozhokkokosovich@gmail.com>
735560e to
fabebae
Compare
|
@tsegismont I published solution where tried to go FileChannel option but within error logic of readAllBytes. Check when you have time, please. |
Closes eclipse-vertx#5677 The improvement consists in creating the buffer upfront and using Netty API to read the file channel. Signed-off-by: Thomas Segismont <tsegismont@gmail.com>
Closes eclipse-vertx#5677 The improvement consists in creating the buffer upfront and using Netty API to read the file channel. Signed-off-by: Thomas Segismont <tsegismont@gmail.com>
Motivation:
In this short PR I did optimization that previously was discussed with @franz1981 in this issue: #5665 regarding avoiding of extra bytes copy in FileSystemImpl.readFileInternal method.
Additional notes:
Conformance:
Everything is signed, my eclipse account is identical to github one.